Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Executor & data provider payouts #464

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Executor & data provider payouts #464

wants to merge 9 commits into from

Conversation

hacheigriega
Copy link
Member

@hacheigriega hacheigriega commented Jan 13, 2025

Motivation

Implementation of data executor payout calculation and total execution gas consumption calculation in both uniform and divergent gas reporting scenarios.

See this table for broad descriptions of the payout logic.

Explanation of Changes

  • Executor payout (uniform & divergent cases)
  • Data provider payout
  • Re-ordering error detection
  • Add base fee, which is charged for every data request
  • Test with updated core contract
  • Burn 20% of executor payout in case of ErrInvalidFilterInput, ErrNoConsensus, or a tally VM execution error
  • Add more tests (particularly ones with proxy payouts)
  • Combine burn messages into one and send distributions in a sorted way (burn -> data proxies -> executors)
  • Add events to show details of payout calculation outcomes

Related PRs and Issues

Closes #456 & #458

@hacheigriega hacheigriega changed the base branch from main to hy/missing-reveals January 13, 2025 22:11
@hacheigriega hacheigriega marked this pull request as draft January 14, 2025 10:34
@hacheigriega hacheigriega changed the title Data executor payout Executor & data provider payouts Jan 14, 2025
Base automatically changed from hy/missing-reveals to main January 15, 2025 18:36
@hacheigriega hacheigriega marked this pull request as ready for review January 16, 2025 19:43
Comment on lines 133 to 135
ctx.EventManager().EmitEvent(sdk.NewEvent(types.EventTypeBaseFeeBurn,
sdk.NewAttribute(sdk.AttributeKeyAmount, baseFee.String()),
))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be easier if all attributes get emitted under a single event. If that's too much of a headache than we should at least add the DR_ID as an attribute so we can link the event to the relevant DR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DistributionsFromGasCalculation() constructs a series of event attributes and emits them at once at the end. Since an attribute is just a key-value pair, proxy & executor gas attributes' values follow the "ID,amount" pattern.

vmRes, err := k.ExecuteTallyProgram(ctx, req, filterResult, reveals)
if err != nil {
result.Result = []byte(err.Error())
vmRes, tallyErr = k.ExecuteTallyProgram(ctx, req, filterResult, reveals)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The execution needs to be aware of the base gas fee that was already consumed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the base gas be taken from the execution gas limit while the tally program uses the tally gas limit?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the base gas is charged from the tally gas limit. If we were to take it from the execution gas limit all the overlay nodes would also have to consider the base gas cost when calculating their individual limits. And we said it is to cover some of the computational load a DR causes for a validator that are not charged directly like the filter and tally VM; think basic consensus check, median gas price calculation, etc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK added. Perhaps BuildFilter() should check if the filter gas cost is within the tally limit?

}
return dists, gasUsed.Uint64()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gasUsed is not guaranteed to fit in a uint64 right? Lets say I change the price of my data proxy to 1 billion SEDA from 1 attoseda. Due to the delayed update the overlay computes its gas cost using the 1 attoseda fee but when the tally checks the price it has flipped and is now 1 billion SEDA.

Obviously an extreme example but think it's worth considering.

// GasCostBase is the base gas cost for a data request.
uint64 gas_cost_base = 5;
// GasCostCommit is the gas cost for a commit charged under certain scenarios.
uint64 gas_cost_commit = 6;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is this used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We charge the base gas cost for every data request.

When the request times out or when there is no basic consensus, we charge the commit cost for each executor that did commit (CalculateCommitterPayouts())

Comment on lines 139 to 142
ctx.EventManager().EmitEvent(sdk.NewEvent(types.EventTypeExecutorRewardUniform,
sdk.NewAttribute(types.AttributeExecutor, executor),
sdk.NewAttribute(sdk.AttributeKeyAmount, payout.String()),
))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In terms of events I think we're only really interested in 2 values: medianGas and lowestReporter (which can be empty for uniform scenarios). This will allow us to simple add those attributes to the DR completion event and simplify indexing in that regard. The adjusted values after the shares calculation we will receive from the contract when it sends the actual SEDA amounts to the identities.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take a look at the function DistributionsFromGasCalculation() and let me know what you think. If we want those values, we can add those values to the GasCalculation struct and emit them as events later, too.

}

var execGasUsed uint64
if req.ReplicationFactor == 1 || areGasReportsUniform(gasReports) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not add the RF=1 case to areGasReportsUniform? Since we check for 0 there as well.

Copy link
Member Author

@hacheigriega hacheigriega Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the replication factor check and changed the check in areGasReportsUniform to

if len(reports) <= 1 {
  return true
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

✨ Data request executor payout & slashing
3 participants